#pragma once

#include "../libs/httplib.h"
#include "../libs/easylog.h"
#include "../util.hpp"
#include "../controllers/medicinecontroller.hpp"

namespace pharmacy_server
{
    struct MedicineBusiness
    {
        static void add_medicine(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("addMedicine body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto name = root["name"].asString();
                auto category = root["category"].asString();
                auto supplier = root["supplier"].asString();
                auto price = root["price"].asFloat();
                auto stock = root["stock"].asInt();
                auto threshold = root["threshold"].asInt();
                auto validity = root["validity"].asInt();

                Result result = MedicineController::instance().add_medicine(name, category, supplier, price, stock, threshold, validity);
                rsp.set_content(result.serialize(), "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("addMedicine business error: {}", e.what());
            }
        }

        static void edit_medicine(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("editMedicine body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto id = root["id"].asInt();
                auto name = root["name"].asString();
                auto category = root["category"].asString();
                auto supplier = root["supplier"].asString();
                auto price = root["price"].asFloat();
                auto stock = root["stock"].asInt();
                auto threshold = root["threshold"].asInt();
                auto validity = root["validity"].asInt();

                Result result = MedicineController::instance().edit_medicine(id, name, category, supplier, price, stock, threshold, validity);
                rsp.set_content(result.serialize(), "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("editMedicine business error: {}", e.what());
            }
        }

        static void delete_medicine(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("deleteMedicine body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto name = root["name"].asString();

                rsp.set_content(MedicineController::instance().delete_medicine(name).serialize(),
                    "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("deleteMedicine business error: {}", e.what());
            }
        }

        static void query_medicines_by_category(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("queryMedicinesByCategory body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto category = root["category"].asString();

                rsp.set_content(MedicineController::instance().query_medicines_by_category(category).serialize(),
                    "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("queryMedicinesByCategory business error: {}", e.what());
            }
        }

        static void query_medicines_by_keyword(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("queryMedicineByKeyword body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto keyword = root["keyword"].asString();

                rsp.set_content(MedicineController::instance().query_medicines_by_keyword(keyword).serialize(),
                    "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("queryMedicineByKeyword business error: {}", e.what());
            }
        }

        static void query_medicine_by_name(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("getMedicineByName body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto name = root["name"].asString();

                rsp.set_content(MedicineController::instance().query_medicine_by_name(name).serialize(),
                    "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("getMedicineByName business error: {}", e.what());
            }
        }

        static void get_medicine(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("getMedicine body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto id = root["id"].asInt();

                rsp.set_content(MedicineController::instance().get_medicine(id).serialize(),
                    "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("getMedicine business error: {}", e.what());
            }
        }

        static void take_medicine(const httplib::Request& req, httplib::Response& rsp)
        {
            try
            {
                easylog::debug("takeMedicine body: {}", req.body);

                Json::Value root = json_util::deserialize(req.body);
                auto username = root["username"].asString();
                auto medicine_name = root["medicine_name"].asString();
                auto quantity = root["quantity"].asInt();

                Result result = MedicineController::instance().take_medicine(username, medicine_name, quantity);
                rsp.set_content(result.serialize(), "application/json");
            }
            catch (const std::exception& e)
            {
                easylog::error("takeMedicine business error: {}", e.what());
            }
        }
    };
}